package com.yanqu.road.server.manger;

import com.yanqu.road.entity.enums.eChannelType;
import com.yanqu.road.entity.servercenter.ServerInfo;
import com.yanqu.road.logic.bussiness.config.ForbiddenWordBussiness;
import com.yanqu.road.logic.config.ServerConfig;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ForbiddenWordMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(ForbiddenWordMgr.class.getName());

    private static List<Pattern> thirdPartyPatterns;

    private static List<Pattern> forbiddenPatternList;

    private static final int worldSpeakType = 1;

    private static final int unionSpeakType = 2;

    private static final int nickNameType = 3;

    private static Pattern wechatPattern;

    private static Pattern qqPattern;
    private static Pattern namePattern;

    private static Pattern onlyNumberPattern;


    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        return false;
    }

    @Override
    public boolean reloadData() {
        int channelId = 0;
        ServerInfo serverInfo = ServerListMgr.getServerInfo(ConfigHelper.getLong("serverId"));
        if (serverInfo != null) {
            channelId = serverInfo.getChannelId();
        }
        Map<Integer, List<String>> forbiddenWordList = ForbiddenWordBussiness.getForbiddenWordMap(channelId);
        forbiddenPatternList = new ArrayList<>();
        thirdPartyPatterns = new ArrayList<>();
        addForbiddenPattern(forbiddenWordList, worldSpeakType, forbiddenPatternList);
        wechatPattern = Pattern.compile("^[0-9a-zA-Z]+$");
        qqPattern = Pattern.compile("^[0-9]+$");
        namePattern = Pattern.compile(".*\\d.*\\d.*");
        onlyNumberPattern = Pattern.compile("^[0-9]+$");
        return true;
    }

    @Override
    public boolean reloadConfig() throws Exception {
        return true;
    }

    private void addForbiddenPattern(Map<Integer, List<String>> forbiddenWordList, int worldSpeakType, List<Pattern> forbiddenPatternList) {
        if (forbiddenWordList.containsKey(worldSpeakType)) {
            for (String regix : forbiddenWordList.get(worldSpeakType)) {
                try {
                    String lowerCaseStr = regix.toLowerCase();
                    forbiddenPatternList.add(Pattern.compile(lowerCaseStr));
                } catch (Exception e) {
                    logger.error("ForbiddenWordMgr reload error.", e);
                }
            }
        }
    }

    public static boolean isForbidden(String word) {
        if (word.trim().length() == 0) {
            return true;
        }
        //去空格
        String notBlankWord = removeBlankWord(word);
        notBlankWord = notBlankWord.replaceAll("[\\t\\n\\r]", "");
        //小写
        notBlankWord = notBlankWord.toLowerCase();
        for (Pattern regix : forbiddenPatternList) {
            Matcher matcher = regix.matcher(notBlankWord);
            if (matcher.matches()) {
                return true;
            }
        }
        return isPlatformForbidden(notBlankWord);
    }

    public static boolean isWechatForbidden(String wechat) {
        if (StringUtils.isNullOrEmpty(wechat)) {
            return false;
        }
        Matcher matcher = wechatPattern.matcher(wechat);
        if (!matcher.matches()) {
            return true;
        }
        return false;
    }

    public static boolean isQQForbidden(String qq) {
        if (StringUtils.isNullOrEmpty(qq)) {
            return false;
        }
        Matcher matcher = qqPattern.matcher(qq);
        if (!matcher.matches()) {
            return true;
        }
        return false;
    }

    private static boolean isPlatformForbidden(String word){
        if(1 == ServerConfig.PLATFORM_FORBIDDEN_WORD){//平台敏感屏蔽词
            for (Pattern regix : thirdPartyPatterns) {
                Matcher matcher = regix.matcher(word);
                if (matcher.matches()) {
                    return true;
                }
            }
        }
        if (1 == ServerConfig.OVERSEAS_PLATFORM_FORBIDDEN_WORD) {
            return ForbiddenWordOverSeasMgr.isForbidden(word);
        }
        return false;
    }

    public static boolean isUnionForbidden(String word) {
        return isForbidden(word);
//        String notBlankWord = word.replace(" ", "");
//        for (Pattern regix : forbiddenPatternList) {
//            Matcher matcher = regix.matcher(notBlankWord);
//            if (matcher.matches()) {
//                return true;
//            }
//        }
//        return isPlatformForbidden(word);
    }

    public static boolean isUnionNameForbidden(String word) {
        return isNickNameForbidden(word);
//        String notBlankWord = word.replace(" ", "");
//        for (Pattern regix : forbiddenPatternList) {
//            Matcher matcher = regix.matcher(notBlankWord);
//            if (matcher.matches()) {
//                return true;
//            }
//        }
//        return isPlatformForbidden(word);
    }

    public static boolean isNickNameForbidden(String nickName) {
        boolean isForbidden = isForbidden(nickName);
        if(!isForbidden){
            int channelId = ServerListMgr.getChannelId(ConfigHelper.getLong("serverId"));
            if(eChannelType.isMainLandChannel(channelId)) {
                String notBlankWord = nickName;
                notBlankWord = notBlankWord.replaceAll("[\\t\\n\\r]", "");
                Matcher nameMatcher = namePattern.matcher(notBlankWord);
                isForbidden = nameMatcher.matches();
            }
        }
        return isForbidden;
    }

    public static int getThirdPartyForbiddenNum() {
        if (thirdPartyPatterns == null) {
            return 0;
        }
        return thirdPartyPatterns.size();
    }

    /**
     * 增加敏感词
     * @param words
     */
    public static void addForbiddenWord(List<String> words) {
        thirdPartyPatterns = new ArrayList<>();
        List<Pattern> patternList = new ArrayList<>();
        for (String word : words) {
            word = word.trim();
            if (StringUtils.isNullOrEmpty(word)) {
                continue;
            }
            try {
                word = word.toLowerCase();
                patternList.add(Pattern.compile(translateWord(word)));
            } catch (Exception e) {
                logger.error("ForbiddenWordMgr add forbidden error.", e);
            }
        }
        thirdPartyPatterns = patternList;
    }

    public static String translateWord(String word) {
        StringBuffer sb = new StringBuffer();
        word = word.replace("\\", "\\\\");
        word = word.replace("*", "\\*");
        word = word.replace(".", "\\.");
        word = word.replace("?", "\\?");
        word = word.replace("+", "\\+");
        word = word.replace("$", "\\$");
        word = word.replace("^", "\\^");
        word = word.replace("[", "\\[");
        word = word.replace("]", "\\]");
        word = word.replace("(", "\\(");
        word = word.replace(")", "\\)");
        word = word.replace("{", "\\{");
        word = word.replace("}", "\\}");
        word = word.replace("/", "\\/");
        sb.append(".*");
        sb.append(word);
        sb.append(".*");
        return sb.toString();
    }

    /**
     * 去空格，英文词组间空格不去除
     * @param word
     * @return
     */
    private static String removeBlankWord(String word){
        StringBuffer removeBlankWord = new StringBuffer();      //结果
        try {
            String[] splitList = word.split("\\s+");         //拆分一个或多个空格
            Vector<Boolean> engHeadList = new Vector<>();           //头是否为字母
            Vector<Boolean> engTailList = new Vector<>();           //尾是否为字母
            String patternHead = "[a-zA-Z].+$";                     //配置头为字母的正则表达式
            String patternTail = ".*[a-zA-Z]+$";                     //配置尾为字母的正则表达式
            removeBlankWord.append(splitList[0]);                   //加入首分量
            for (String string : splitList) {
                //匹配当前字符串
                boolean isHeadWord = Pattern.matches(patternHead, string);
                boolean isTailWord = Pattern.matches(patternTail, string);
                //结果塞入数组
                engHeadList.add(isHeadWord);
                engTailList.add(isTailWord);
            }
            //取出结果,对应加入分隔或不加入
            for (int num = 0; num < engHeadList.size(); num++) {
                if (engHeadList.size() > num + 1 && engTailList.size() > num + 1) {
                    if (engTailList.get(num) && engHeadList.get(num + 1)) {
                        removeBlankWord.append(" " + splitList[num + 1]);
                    } else if (!engTailList.get(num) || !engHeadList.get(num + 1)) {
                        removeBlankWord.append(splitList[num + 1]);
                    }
                } else {
                    break;
                }
            }
        }catch (Exception e){
            logger.error("isForbidden error:", e);
            removeBlankWord = new StringBuffer(word.replace(" ", ""));
        }
        return removeBlankWord.toString();
    }

    public static void main(String[] args)throws Exception {
		/*forbiddenPatternList = new ArrayList<>();
		forbiddenPatternList.add(Pattern.compile(".*[加伽迦珈茄＋+＋＋┼嘉佳嫁痂夹架驾枷傢笳].{0,5}(公告|家族频道|家族信息|家xun|家训|jia训|滚屏|会长|族长|简介).*|.*(公告|家族频道|家族信息|家xun|家训|jia训|滚屏|会长|族长|简介).{0,5}[加伽迦珈茄＋+＋＋┼嘉佳嫁痂夹架驾枷傢笳].*|.*(公告|家族频道|家族信息|家xun|家训|jia训|滚屏|会长|族长|简介).{0,5}[QqＱｑ扣釦抠抇宭峮箘羣踆囷裠帬君郡珺捃莙桾vVｖＶ∨Ww纬违菋葳卫委维藯唯微围薇唯伟炜矀徵癓維覹霺徽㣲嶶溦魏巍危萎崴楲威胃未畏].*|.*[QqＱｑ扣釦抠抇宭峮箘羣踆囷裠帬君郡珺捃莙桾vVｖＶ∨Ww纬违菋葳卫委维藯唯微围薇唯伟炜矀癓維覹霺徽徵㣲嶶溦魏巍危萎崴楲威胃未畏].{0,5}(公告|家族频道|家族信息|家xun|家训|jia训|滚屏|会长|族长|简介).*|.*[VvｖＶwW微徵威违维魏唯卫薇維为藯喂蔚巍隗玮惟委苇炜维围楲伟矀癓覹霺嶶溦危萎嶉徽荟绘].{0,5}[xXｘＸ讯信新薪欣芯鑫辛馨昕訫伈莘昕锌忻].*|.*[加嘉＋+＋+佳价伽迦茄荚枷笳稼葭泇拁跏鉫乫].{0,5}[VvｖＶ讯嶉徵微威违维魏唯卫薇藯蔚巍隗韦玮維惟苇炜维围伟矀癓覹霺嶶溦危委萎徽荟绘味].*|.*[VvｖＶ讯嶉徵微威违维魏唯卫薇藯蔚巍隗韦玮維惟苇炜维围伟矀癓覹霺嶶溦危委萎徽荟绘味].{0,3}[加嘉＋+＋+佳价伽迦茄荚枷笳稼葭泇拁跏鉫乫].*|.*[加嘉＋+＋+佳价伽迦茄荚枷笳稼葭泇拁跏鉫乫].{0,3}[QqＱｑ扣釦抠抇裙宭峮箘羣踆囷裠帬君郡珺捃莙桾].*|.*[QqＱｑ扣釦抠抇裙宭峮箘羣踆囷裠帬君郡珺捃莙桾].{0,3}[QqＱｑ扣釦抠抇宭峮箘羣踆囷裠帬君郡珺捃莙桾].*|.*[QqＱｑ扣釦抠抇裙宭峮箘羣踆囷裠帬君郡珺捃莙桾].{0,3}[加嘉＋+＋+佳价伽迦茄荚枷笳稼葭泇拁跏鉫乫].*|.*(扌口).{0,3}(扌口).*|.*力o .*w e i.*|.*w e i.*亻言.*|.*机器人.*|.*不.{0,2}[加进近家].{0,17}(踢|提|剔|飞{0,2}机|机{0,2}票|清理).*"));
		System.out.println(isForbidden("欺我龙城者，天天黑死你"));
		System.out.println(isForbidden("兄弟们不要打杨家，以后准时六点开副本"));*/
//        wechatPattern = Pattern.compile("^[0-9a-zA_Z]+$");
//        qqPattern = Pattern.compile("^[0-9]+$");
//        System.out.println(isQQForbidden("471030918"));
//        System.out.println(isQQForbidden("471030918xxx"));
//        System.out.println(isWechatForbidden("xxads213121"));
//        System.out.println(isWechatForbidden("xxads213121==2"));
//        FileReader fileReader = new FileReader("D:/XXXX.txt");
//        BufferedReader bufferedReader = new BufferedReader(fileReader);
//        String s = bufferedReader.readLine();
//        FileWriter fileWriter = new FileWriter("D:/newXXX.txt",true);
//        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
//
//        while (s != null) {
//            try {
//                Pattern.compile(s);
//                bufferedWriter.write(s+"\n");
//            } catch (Exception e) {
//                System.out.println(s);
//            }
//            s = bufferedReader.readLine();
//        }
//        FileReader fileReader = new FileReader("D:\\TempSpaces\\敏感词2.txt");
//        BufferedReader bufferedReader = new BufferedReader(fileReader);
//        FileWriter fileWriter = new FileWriter("D:\\TempSpaces\\敏感词new2.txt",true);
//        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
//        StringBuffer sb = new StringBuffer();
//        int i = 0;
//        do{
//            String lineString = bufferedReader.readLine();
//            if(null == lineString) {
//                break;
//            }
//            String[] lineArr = lineString.split("\\|");
//            for(String tempStr : lineArr){
//                tempStr = tempStr.trim();
//                if(tempStr.length() <= 0){
//                    continue;
//                }
//                boolean addSpe = true;
//                if(tempStr.contains("\\") || tempStr.contains("*") || tempStr.contains(".") || tempStr.contains("?") ||
//                        tempStr.contains("+") || tempStr.contains("$") || tempStr.contains("^") || tempStr.contains("[") ||
//                        tempStr.contains("]") || tempStr.contains("(") || tempStr.contains(")") || tempStr.contains("{") ||
//                        tempStr.contains("}") || tempStr.contains("/") || tempStr.length() < 2){
//                    addSpe = false;
//                }
//                if(addSpe){
//                    String newStr = "";
//                    for(int j = 0; j < tempStr.length(); j++){
//                        if(j == tempStr.length() - 1){
//                            newStr = newStr + tempStr.charAt(j);
//                        }else {
//                            newStr = newStr + tempStr.charAt(j) + "( |&)*?";
//                        }
//                    }
//                    tempStr = newStr;
//                }else {
//                    tempStr = tempStr.replace("\\", "\\\\\\\\");
//                    tempStr = tempStr.replace("*", "\\\\*");
//                    tempStr = tempStr.replace(".", "\\\\.");
//                    tempStr = tempStr.replace("?", "\\\\?");
//                    tempStr = tempStr.replace("+", "\\\\+");
//                    tempStr = tempStr.replace("$", "\\\\$");
//                    tempStr = tempStr.replace("^", "\\\\^");
//                    tempStr = tempStr.replace("[", "\\\\[");
//                    tempStr = tempStr.replace("]", "\\\\]");
//                    tempStr = tempStr.replace("(", "\\\\(");
//                    tempStr = tempStr.replace(")", "\\\\)");
//                    tempStr = tempStr.replace("{", "\\\\{");
//                    tempStr = tempStr.replace("}", "\\\\}");
//                    tempStr = tempStr.replace("/", "\\\\/");
//                }
//                sb.append(".*");
//                sb.append(tempStr);
//                sb.append(".*");
//                i++;
//                if(i % 100 == 0){
//                    sb.append("\n");
//                }else {
//                    sb.append("|");
//                }
//            }
//        }while (true);
//        bufferedWriter.write(sb.toString());
//        bufferedWriter.flush();
//        bufferedWriter.close();
        FileReader fileReader = new FileReader("D:\\TempSpaces\\敏感词new2.txt");
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        FileWriter fileWriter = new FileWriter("D:\\TempSpaces\\敏感词2.sql",true);
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
        StringBuffer sb = new StringBuffer();
        int i = 1;
        do{
            String lineString = bufferedReader.readLine();
            if(null == lineString) {
                break;
            }
            i++;
            String sqlStr = "INSERT INTO `t_s_forbidden_word` (`type`, `content`) VALUES ('1', \"" + lineString + "\");";
            sb.append(sqlStr);
            sb.append("\n");
        } while (true);
        bufferedWriter.write(sb.toString());
        bufferedWriter.flush();
        bufferedWriter.close();
    }

    public static boolean isNumber(String checkString) {
        if (StringUtils.isNullOrEmpty(checkString)) {
            return false;
        }
        Matcher matcher = onlyNumberPattern.matcher(checkString);
        if (matcher.matches()) {
            return true;
        }
        return false;
    }

    public static boolean checkPassWordFormat(String checkString, int lengthMin, int lengthMax) {
        if (null == checkString)
            return false;
        if (!isNumber(checkString))
            return false;
        if (lengthMin > lengthMax)
            return false;
        if (checkString.length() < lengthMin)
            return false;
        if (checkString.length() > lengthMax)
            return false;
        return true;
    }
}
